package com.block.merchant.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.block.common.exception.NotifyExceptionService;
import com.block.common.model.param.PushApiKeyParam;
import com.block.common.service.ISourcePushResultInfoCommonService;
import com.block.common.service.LogFactory;
import com.block.datapush.enums.PushStatusEnum;
import com.block.datapush.factory.PushApiFactory;
import com.block.datapush.factory.PushExtDataFactory;
import com.block.datapush.model.ProtocolInfoEntity;
import com.block.datapush.model.PushQueryParam;
import com.block.datapush.model.dto.NoticeParamDTO;
import com.block.datapush.model.result.PushApiResult;
import com.block.db.entity.MemberSourceInfo;
import com.block.db.entity.MerchantBaseInfo;
import com.block.db.entity.MerchantDataNoticeLog;
import com.block.db.entity.MerchantDataPushInfo;
import com.block.db.mapper.MemberSourceInfoMapper;
import com.block.db.mapper.MerchantDataPushInfoMapper;
import com.block.merchant.model.dto.MerchantOrderDTO;
import com.block.merchant.model.dto.PushSettleDTO;
import com.block.merchant.model.result.DataPushResult;
import com.block.merchant.model.result.MatchMerchantInfo;
import com.block.merchant.service.*;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.transaction.support.TransactionTemplate;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 商户推送信息表 服务实现类
 * </p>
 *
 * @author 
 * @since 2023-08-12
 */
@Service
@Deprecated
public class MerchantDataPushInfoServiceImpl extends ServiceImpl<MerchantDataPushInfoMapper, MerchantDataPushInfo>
        implements IMerchantDataPushInfoService{

    private static final Logger log = LogFactory.getMerchantLog();

    @Autowired
    TransactionTemplate transactionTemplate;
    @Autowired
    IMerchantBaseInfoService merchantBaseInfoService;
    @Autowired
    NotifyExceptionService notifyExceptionService;
    @Resource
    MemberSourceInfoMapper memberSourceInfoMapper;

    @Override
    public PushApiKeyParam getPushKeyInfo(MerchantBaseInfo merchantBaseInfo, MemberSourceInfo memberSourceInfo){
        PushApiKeyParam pushApiKeyParam = new PushApiKeyParam();
        pushApiKeyParam.setInfoId(String.valueOf(merchantBaseInfo.getId()));
        pushApiKeyParam.setInfoName(merchantBaseInfo.getInfoName());
        pushApiKeyParam.setApiCode(merchantBaseInfo.getApiCode());
        pushApiKeyParam.setApiKey(merchantBaseInfo.getApiKey());
        pushApiKeyParam.setApiSecret(merchantBaseInfo.getApiSecret());
        pushApiKeyParam.setPubKey(merchantBaseInfo.getApiPubKey());
        pushApiKeyParam.setPriKey(merchantBaseInfo.getApiPriKey());
        pushApiKeyParam.setCheckUrl(merchantBaseInfo.getApiCheckUrl());
        pushApiKeyParam.setRegisterUrl(merchantBaseInfo.getApiRegisterUrl());
        pushApiKeyParam.setQueryUrl(merchantBaseInfo.getApiQueryUrl());
        pushApiKeyParam.setPriceType(merchantBaseInfo.getPriceType());
        pushApiKeyParam.setTypeRate(merchantBaseInfo.getTypeRate());

        /**
         * 协议地址
         */
        List<ProtocolInfoEntity> protocolList = PushExtDataFactory.getService(merchantBaseInfo.getFactoryType()).getProtocolUrl(merchantBaseInfo, memberSourceInfo, null);
        if (CollUtil.isNotEmpty(protocolList)){
            pushApiKeyParam.setProtocolUrl(protocolList.get(0).getProtocolUrl());
        }
        return pushApiKeyParam;
    }

    @Override
    public MerchantDataPushInfo saveInitPushData( MemberSourceInfo memberSourceInfo, MerchantOrderDTO merchantOrderDTO){
        MerchantDataPushInfo dataPushInfo = new MerchantDataPushInfo();
        dataPushInfo.setDateInfo(LocalDate.now().toString());
        dataPushInfo.setInfoId(merchantOrderDTO.getInfoId());
        dataPushInfo.setTaskId(merchantOrderDTO.getTaskId());
        dataPushInfo.setDeptId(merchantOrderDTO.getDeptId());
//        dataPushInfo.setOrderId(merchantOrderDTO.getOrderId());
//        dataPushInfo.setOrderItemId(merchantOrderDTO.getOrderItemId());
        dataPushInfo.setPriceAmount(merchantOrderDTO.getPriceAmount());
        dataPushInfo.setCostAmount(merchantOrderDTO.getCostAmount());
        dataPushInfo.setPayAmount(merchantOrderDTO.getPayAmount());
        dataPushInfo.setUid(memberSourceInfo.getUid());
        dataPushInfo.setChannelCode(memberSourceInfo.getChannelCode());
        dataPushInfo.setChannelName(memberSourceInfo.getChannelName());
        dataPushInfo.setAppCode(memberSourceInfo.getAppCode());
        dataPushInfo.setAppName(memberSourceInfo.getAppName());
        dataPushInfo.setStatus(PushStatusEnum.INIT.getValue());

        boolean save = this.save(dataPushInfo);
        if (!save){
            return null;
        }
        return this.getById(dataPushInfo);
    }

    /**
     * 查询待
     * status = WAIT_QUERY
     */
    @Override
    public void queryPushData(){
        List<MerchantDataPushInfo> pushInfoList = this.baseMapper.getWaitQueryPushDataList();
        for (MerchantDataPushInfo merchantDataPushInfo : pushInfoList) {
                /// 先进行一次查询，如果没有成功，则判断时间是否超时
                // 查询商户信息
                this.querySinglePushDataInfo(merchantDataPushInfo);
        }
    }

    /**
     * 商户 回调带查询订单  进行查询 操作
     * @param merchantDataPushInfo
     */
    @Override
    public void querySinglePushDataInfo(MerchantDataPushInfo merchantDataPushInfo){

        transactionTemplate.execute(status -> {

            try {
                // 加锁查询推送信息
                MerchantDataPushInfo entityByOrderNoLock = this.baseMapper.getEntityByOrderNoLock(String.valueOf(merchantDataPushInfo.getId()));
                if (!StrUtil.equals(entityByOrderNoLock.getStatus(), PushStatusEnum.WAIT_QUERY.getValue())){
                    log.info("【回调查询】推送数据的状态错误【pushId】{}【pushStatus】{}",
                            entityByOrderNoLock.getId(), entityByOrderNoLock.getStatus());
                    return false;
                }

                // 查询商户信息，拿到密钥信息
                MemberSourceInfo memberSourceInfo = memberSourceInfoMapper.selectById(entityByOrderNoLock.getUid());
                MerchantBaseInfo merchantBaseInfo = merchantBaseInfoService.getById(entityByOrderNoLock.getInfoId());
                PushApiKeyParam pushKeyInfo = this.getPushKeyInfo(merchantBaseInfo, memberSourceInfo);

                PushQueryParam pushQueryParam = new PushQueryParam();
                pushQueryParam.setOrderNo(String.valueOf(entityByOrderNoLock.getId()));
                pushQueryParam.setOutOrderNo(String.valueOf(entityByOrderNoLock.getOutOrderNo()));


                pushQueryParam.setMobile(memberSourceInfo.getMobile());

                // 进行查询操作
                PushApiResult pushApiResult = PushApiFactory.getService(merchantBaseInfo.getFactoryType())
                        .queryResult(pushQueryParam, pushKeyInfo, entityByOrderNoLock.getExtJson());
                log.info("【回调查询】查询结束【pushQueryParam】{}【pushApiResult】{}", JSON.toJSONString(pushQueryParam), JSON.toJSONString(pushApiResult));

                // 更新推送查询结果
                MerchantDataPushInfo updateEntity = new MerchantDataPushInfo();
                updateEntity.setId(entityByOrderNoLock.getId());

                updateEntity.setQueryStatus(pushApiResult.getCode()+'|'+pushApiResult.getMessage());
                updateEntity.setQueryResultInfo(pushApiResult.getResultInfo());

                // 如果不是成功，并且超时了，就将状态改为超时
                LocalDateTime createTime = merchantDataPushInfo.getCreateTime();
                if (StrUtil.equals(pushApiResult.getStatus(), PushStatusEnum.SUCCESS.getValue())){
                    updateEntity.setStatus(pushApiResult.getStatus());
                }

                if (LocalDateTime.now().isAfter(createTime.plusHours(2L)) &&
                        !StrUtil.equals(pushApiResult.getStatus(), PushStatusEnum.SUCCESS.getValue())){
                    updateEntity.setStatus(PushStatusEnum.TIMEOUT.getValue());
                }

                boolean b = this.updateById(updateEntity);
                if (!b){
                    return false;
                }

                // 账户结算
                PushSettleDTO pushSettleDTO = new PushSettleDTO();
                pushSettleDTO.setPushFlag(false);// 此处只统计推送成功的量，为了不重复统计，故此处给false
                pushSettleDTO.setSettleFlag(pushApiResult.isSettleFlag());
                pushSettleDTO.setSettleAmount(entityByOrderNoLock.getPriceAmount());

                pushSettleDTO.setChannelCode(entityByOrderNoLock.getChannelCode());

                pushSettleDTO.setInfoId(merchantBaseInfo.getId());
                pushSettleDTO.setInfoName(merchantBaseInfo.getInfoName());
                pushSettleDTO.setInfoType(merchantBaseInfo.getInfoType());
                pushSettleDTO.setTaskId(entityByOrderNoLock.getTaskId());

                pushSettleDTO.setOrderId(String.valueOf(entityByOrderNoLock.getOrderId()));
                pushSettleDTO.setOrderItemId(String.valueOf(entityByOrderNoLock.getOrderItemId()));
                pushSettleDTO.setPushPoolId(String.valueOf(entityByOrderNoLock.getId()));
                merchantBaseInfoService.handlePushToData(pushSettleDTO,memberSourceInfo);

            }catch (Exception exception){
                exception.printStackTrace();
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                String content = StrUtil.format("【infoId】{}【pushId】{}", merchantDataPushInfo.getInfoId(), merchantDataPushInfo.getId());
                notifyExceptionService.notifyNoticeInfo("PUSH_DATA_WAIT_QUERY", "商户推送数据查询", content, exception);
            }
            return true;
        });
    }

    /**
     * 查询授权信息
     * @param merchantOrderDTO
     * @param memberSourceInfo
     * @return
     * @throws Exception
     */
    @Override
    public MatchMerchantInfo queryApprove(MerchantOrderDTO merchantOrderDTO, MemberSourceInfo memberSourceInfo) throws Exception {

        MerchantBaseInfo merchantBaseInfo = merchantBaseInfoService.getById(merchantOrderDTO.getInfoId());

        MerchantDataPushInfo merchantDataPushInfo = this.getById(merchantOrderDTO.getPushPoolId());
        String orderNo = String.valueOf(merchantDataPushInfo.getId());

        PushApiKeyParam pushApiKeyParam = this.getPushKeyInfo(merchantBaseInfo, memberSourceInfo);

        JSONObject extJson = new JSONObject();

        MerchantDataPushInfo updateEntity = new MerchantDataPushInfo();
        updateEntity.setId(merchantDataPushInfo.getId());

        MatchMerchantInfo matchMerchantInfo = new MatchMerchantInfo();
        matchMerchantInfo.setMatchSuccess(false);

        PushApiResult queryApproveResult = PushApiFactory.getService(merchantBaseInfo.getFactoryType()).queryApprove(orderNo, pushApiKeyParam, memberSourceInfo, extJson);
        updateEntity.setCode(queryApproveResult.getCode());
        updateEntity.setMessage(queryApproveResult.getMessage());
        updateEntity.setResultInfo(queryApproveResult.getResultInfo());
        updateEntity.setOutOrderNo(queryApproveResult.getOutOrderNo());
        updateEntity.setApproveUrl(queryApproveResult.getApproveUrl());
        updateEntity.setApproveFlag(1);
        updateEntity.setUid(memberSourceInfo.getUid());
        updateEntity.setOrderId(merchantOrderDTO.getOrderId());
        updateEntity.setOrderItemId(merchantOrderDTO.getOrderItemId());
        if (!queryApproveResult.isPushSuccess()){
            // 获取授权地址失败
            updateEntity.setStatus(PushStatusEnum.GET_APPROVE_FAILED.getValue());
            matchMerchantInfo.setMatchSuccess(false);
        }else{
            updateEntity.setStatus(queryApproveResult.getStatus());

            matchMerchantInfo.setMatchSuccess(true);
            matchMerchantInfo.setApproveUrl(queryApproveResult.getApproveUrl());
        }
        boolean updateRes = this.updateById(updateEntity);
        log.info("【API商户信息匹配】获取授权结果，更新订单结果【updateRes】{}【orderNo】{}【uid】{}【matchMerchantInfo】{}",
                updateRes, orderNo, memberSourceInfo.getUid(), JSON.toJSONString(matchMerchantInfo));
        return matchMerchantInfo;
    }

}
